#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

// GPIO 在sys/class/gpio 目录下
// 会有几个gpiochipX 
// 比如gpiochip96 :base(从96开始) label(名字) ngpio(这个文件夹下有多少个IO)
//GPIO4_IO16  GPIO4->对应的是gpiochip96 所以IO编号是96+16 = 112
//! 想使用gpio就得先导出 export 有些是不可以导出的

// 导出后会有一个gpiox的文件夹 会有 active_low / device / dircetion /edge /power /valu 文件
// direction : 配置GPIO引脚为输入或者输出模式 "in" / "out"
// value : 输出模式就是写入  输入模式就是读取这个
// active_low：1为高电平还是低电平
// edge:上升沿触发“rising”/下降沿触发"falling"/边缘触发"both"/非中断"none"
// 用完之后就unexport

static char gpio_path[100];
static int gpio_config(const char *attr,char *val)
{
    char file_path[100];
    int len;
    int fd;
    sprintf(file_path,"%s/%s",gpio_path,attr);
    printf("cmd is %s\r\n",file_path);
    if(0 > (fd = open(file_path, O_WRONLY)))
    {
        perror("open error");
        return fd;
    }
    len = strlen(val);
    if (len != write(fd, val, len)) {
        perror("write error");
        close(fd);
        return -1;
    }
    close(fd); //关闭文件
    return 0;
}
int main(int argc, char *argv[])
{
    if (3 != argc) {
        fprintf(stderr, "usage: %s <gpio> <value>\n", argv[0]);
        exit(-1);
    }
    /* 判断指定编号的 GPIO 是否导出 */
    sprintf(gpio_path, "/sys/class/gpio/gpio%s", argv[1]);
    if(access(gpio_path, F_OK)) {//如果目录不存在 则需要导出
        int fd;
        int len;
        //! 注意export 是只写文件不可读
        if (0 > (fd = open("/sys/class/gpio/export", O_WRONLY))) {
            perror("open error");
            exit(-1);
        }
        len = strlen(argv[1]);
        if (len != write(fd, argv[1], len)) {//导出 gpio
            perror("write error");
            close(fd);
            exit(-1);
        }
        close(fd); //关闭文件
    }
    /* 配置为输出模式 */
    if (gpio_config("direction", "out"))
        exit(-1);
    /* 极性设置 */
    if (gpio_config("active_low", "0"))
        exit(-1);
    /* 控制 GPIO 输出高低电平 */
    if (gpio_config("value", argv[2]))
        exit(-1);
        /* 退出程序 */
        exit(0);
    return 0;
}